package com.wb.spring.boot.autoconfigure.register;

import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.agent.model.NewService;
import com.ecwid.consul.v1.health.model.HealthService;
import com.wb.spring.boot.autoconfigure.constant.SystemConstant;
import com.wb.spring.boot.autoconfigure.exception.RpcException;
import com.wb.spring.boot.autoconfigure.load.Load;
import com.wb.spring.boot.autoconfigure.model.ServerInfo;
import org.springframework.util.CollectionUtils;

import java.util.*;

public class ConsulRegister implements IRegister {

    private final Load load;

    private final ConsulClient consulClient;

    /**
     * 当前服务的信息
     */
    private final ServerInfo serverInfo;

    /**
     * 服务储存体
     */
    private Map<String, HashSet<String>> server = new HashMap();

    @Override
    public void doRegister() {
        String serviceId = SystemConstant.CONSUL_SERVICE_NAME_PREFIX + "_" + serverInfo.getServiceName() + "_" + serverInfo.getLocalIp() + ":" + serverInfo.getLocalPort();

        NewService newService = new NewService();
        newService.setId(serviceId);
        newService.setName(serverInfo.getServiceName());
        newService.setTags(Arrays.asList("instance"));
        newService.setPort(serverInfo.getLocalPort());
        newService.setAddress(serverInfo.getLocalIp());

        NewService.Check serviceCheck = new NewService.Check();
        serviceCheck.setHttp("http://" + serverInfo.getLocalIp() + ":" + serverInfo.getLocalPort() + "/health");
        serviceCheck.setInterval("10s");
        newService.setCheck(serviceCheck);

        consulClient.agentServiceRegister(newService);

    }

    @Override
    public void refreshServer() {
        //
        String serviceName = serverInfo.getServiceName();

        server.put(serviceName, getInstancesByServiceName(serviceName));
    }

    @Override
    public String getServer(String serviceName) {
        HashSet<String> strings = getInstancesByServiceName(serviceName);
        if (CollectionUtils.isEmpty(strings)) {
            throw new RpcException(serviceName + "不存在提供者, 请检查提供者启动或者配置是否正确。");
        }
        // 通过负载均衡组件获取一个服务，
        return this.load.load(new ArrayList<>(strings));
    }

    @Override
    public void unRegister() {
        String serviceId = SystemConstant.CONSUL_SERVICE_NAME_PREFIX + serverInfo.getServiceName() + "_" + serverInfo.getLocalIp() + ":" + serverInfo.getLocalPort();
        consulClient.agentServiceDeregister(serviceId);
    }

    public ConsulRegister(ConsulClient consulClient, ServerInfo serverInfo, Load load) {
        this.consulClient = consulClient;
        this.serverInfo = serverInfo;
        this.load = load;
    }

    private HashSet<String> getInstancesByServiceName(String serviceName) {
        List<HealthService> healthServiceList = consulClient.getHealthServices(serviceName, false, null).getValue();

        HashSet<String> instances = server.getOrDefault(serviceName,
                new HashSet<>()
        );
        for (HealthService healthService : healthServiceList) {
            String service = healthService.getService().getAddress() + ":" + healthService.getService().getPort();
            instances.add(service);
        }
        return instances;
    }
}
